﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using Minecraft.ContentInstaller;

namespace Minecraft.ModInstaller
{
    public partial class BackupTool : Form
    {
        private string BackupsFolder;

        public BackupTool(string JarPath)
        {
            InitializeComponent();

            BackupsFolder = Path.Combine(
                JarPath.Substring(0, JarPath.LastIndexOf('\\')),
                "ModBackups");

            try
            {
                foreach (string BackupDir in
                    Directory.GetDirectories(BackupsFolder))
                {
                    try
                    {
                        BackupList.Items.Add(new MinecraftBackup(BackupDir));
                    }
                    catch { }
                }
            }
            catch (DirectoryNotFoundException)
            { }
        }

        private void OnShown(object sender, EventArgs e)
        {
            if (BackupList.Items.Count == 0)
            {
                MessageBox.Show("There are no backups.\n\n" +
                    "Backups are created automatically when you install mods."
                    , "Nope", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                this.Close();
            }
        }

        public int BackupCount
        {
            get
            {
                return BackupList.Items.Count;
            }
        }

        public MinecraftBackup LatestBackup
        {
            get
            {
                DateTime LatestTime = new DateTime(1970, 1, 1);
                MinecraftBackup Latest = null;
                foreach (MinecraftBackup BackupItem in BackupList.Items)
                {
                    if (BackupItem.Stamp > LatestTime)
                    {
                        Latest = BackupItem;
                        LatestTime = BackupItem.Stamp;
                    }
                }
                return Latest;
            }
        }

        public void Backup(string GivenName)
        {
            TimeSpan USpan = DateTime.UtcNow - new DateTime(1970, 1, 1);
            long UTimeStamp = (long)Math.Floor(USpan.TotalSeconds);

            string BackupPath = Path.Combine(BackupsFolder, UTimeStamp.ToString());
            if (!Directory.Exists(BackupPath))
                Directory.CreateDirectory(BackupPath);

            try
            {
                File.Copy(MinecraftPaths.Jar, Path.Combine(BackupPath, "minecraft.jar"));
                File.Copy(Path.Combine(MinecraftPaths.GameRoot, "bin\\version"), Path.Combine(BackupPath, "version"));

                TextWriter InfoWriter = new StreamWriter(Path.Combine(BackupPath, "BackupInfo"));
                InfoWriter.Write(GivenName);
                InfoWriter.Close();
            }
            catch (Exception ex)
            {
                if(MessageBox.Show("Unable to save a backup:\n\n" + ex.Message + "\n\nWould you like to continue anyway?",
                    "Error", MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.No)
                    throw ex;
            }
        }

        public void RestoreLast()
        {
            if (LatestBackup == null)
            {
                MessageBox.Show("There are no backups.\n\n" +
                            "Backups are created automatically when you install mods."
                            , "Nope", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                return;
            }

            if (MessageBox.Show(
                "Are you sure you want to revert the installation of \"" + LatestBackup.GivenName + "\" on " + 
                LatestBackup.Stamp.ToString("g") + "?",
                "Restore from backup?", MessageBoxButtons.YesNo,
                MessageBoxIcon.Question) == DialogResult.Yes)
            {
                Restore(LatestBackup);
            }
        }

        private void Restore(MinecraftBackup Restore)
        {
            try
            {
                File.Copy(
                    Path.Combine(Restore.Folder, "minecraft.jar"),
                    Path.Combine(MinecraftPaths.GameRoot, "bin\\minecraft.jar"),
                    true
                );
                File.Copy(
                    Path.Combine(Restore.Folder, "version"),
                    Path.Combine(MinecraftPaths.GameRoot, "bin\\version"),
                    true
                );

                MessageBox.Show("The backup made at " +
                    Restore.Stamp.ToString("g") + " has been " +
                    "successfully restored.", "Restore complete",
                    MessageBoxButtons.OK, MessageBoxIcon.Information);
            }
            catch (Exception ex)
            {
                if (MessageBox.Show("Unable to restore the backup:\n\n" + ex.Message + "\n\n" +
                "Would you like to open the backup folder to copy the files manually?", "Error",
                    MessageBoxButtons.YesNo, MessageBoxIcon.Error) == DialogResult.Yes)
                    System.Diagnostics.Process.Start(Restore.Folder);
            }
        }

        private void RestoreSelected(object sender, EventArgs e)
        {
            try
            {
                Restore((MinecraftBackup)BackupList.SelectedItem);
            }
            catch { }
        }

        private void DeleteSelected(object sender, EventArgs e)
        {
            try
            {
                MinecraftBackup Item = (MinecraftBackup)BackupList.SelectedItem;
                foreach (string F in Directory.GetFiles(Item.Folder))
                {
                    File.Delete(F);
                }
                Directory.Delete(Item.Folder);
                BackupList.Items.RemoveAt(BackupList.SelectedIndex);
            }
            catch (Exception ex)
            {
                MessageBox.Show("Unable to delete the selected backup:" + Environment.NewLine + Environment.NewLine + ex.Message ); 
            }
        }

        private void OnSelectionChanged(object sender, EventArgs e)
        {
            BDelete.Enabled = (BackupList.SelectedIndex > -1);
            BRestore.Enabled = BDelete.Enabled;
        }
    }

    public class MinecraftBackup
    {
        public MinecraftBackup(string BackupPath)
        {
            Folder = BackupPath;

            try
            {
                TextReader InfoReader = new StreamReader(Path.Combine(Folder, "BackupInfo"));
                GivenName = InfoReader.ReadToEnd();
                InfoReader.Close();
            }
            catch
            {
                GivenName = "Untitled";
            }

            if (!File.Exists(Path.Combine(BackupPath, "minecraft.jar")) ||
                !File.Exists(Path.Combine(BackupPath, "version")))
            {
                throw new Exception("Backup is incomplete.");
            }

            long BackupStamp = long.Parse(BackupPath.Substring(BackupPath.LastIndexOf('\\') + 1));
            Stamp = new DateTime(1970, 1, 1).AddSeconds(BackupStamp).ToLocalTime();
        }

        public readonly string GivenName;

        public readonly string Folder;
        public readonly DateTime Stamp;
        public override string ToString()
        {
           return Stamp.ToString("g") + " - " + GivenName;
        }
    }
}
